import { _decorator, assetManager, AssetManager, tween, Component, EditBox, Node, Vec3, Prefab, instantiate } from 'cc';
import UiCover from './UiCover';
import { ParamUI } from './ParamUI';
import { perr, plog } from '../Utils/Tools';
const { ccclass, property } = _decorator;

const DurUiScale = 0.2;

@ccclass('UiManager')
export default class UiManager extends Component {
    public static Instance: UiManager = null;
    @property(Node)
    private NodeUIBase: Node = null;
    // private CurrentUiNode: Node = null;
    private BundleGUI: AssetManager.Bundle = null;
    private MapPrefabs: Map<string, Prefab> = null;
    private EndUiCallback: any = null;
    // Params: any = null;


    onLoad() {
        if (UiManager.Instance === null) {
            UiManager.Instance = this;
        } else {
            this.destroy();
            return;
        }
        this.MapPrefabs = new Map();
        this.NodeUIBase = this.node.getChildByName('NodeUI');
        // this.CurrentUiNode = this.NodeUIBase
        assetManager.loadBundle("GUI", (err, ab: AssetManager.Bundle) => {
            if (err) {
                plog(err)
                return
            }
            this.BundleGUI = ab;
            this.loadUIPrefab("cover", null)
        });
    }

    //加载预制体
    private loadUIPrefab(nameUI: string, callback) {
        this.BundleGUI.load(nameUI, Prefab, (err, data: Prefab) => {
            if (err) {
                plog(err);
                return
            }
            this.MapPrefabs.set(nameUI, data);
            if (callback != null) {
                callback();
            }
        })
    }

    //用预制体创建UI。把ui的node传给回调
    private createUI(nameUI: string, callback: (node_ui: Node) => void): void {
        plog("-------createUI ", nameUI)
        if (this.MapPrefabs.has(nameUI)) {
            let pb = this.MapPrefabs.get(nameUI)
            let node = instantiate(pb)
            this.InitParamUI(node)
            callback(node)
            return
        } else {
            this.BundleGUI.load(nameUI, Prefab, (err, data: Prefab) => {
                if (err) {
                    perr(err)
                    return
                }
                this.MapPrefabs.set(nameUI, data)
                let node = instantiate(data)
                this.InitParamUI(node)
                callback(node)
            })
        }
    }

    //添加一个遮盖层
    // private createCover(type: number = 0, delay: number = 2000): Node {
    //     if (this.MapPrefabs.has('cover')) {
    //         let node = instantiate(this.MapPrefabs.get('cover'))
    //         let cover = node.getComponent(UiCover)
    //         cover.Set(type, delay)
    //         return node
    //     }
    //     return null
    // }
    public InitParamUI(node: Node) {
        let pu = node.addComponent(ParamUI)
        pu.Init()
    }

    public AddCover(node: Node, type: number = 0, delay: number = 2000): Node {
        if (this.MapPrefabs.has('cover')) {
            let nodeCover = instantiate(this.MapPrefabs.get('cover'))
            node.addChild(nodeCover)
            let cover = nodeCover.getComponent(UiCover)
            cover.Set(type, delay)
            return nodeCover;
        }
        console.error("AddCover:", node.name, " cover 1 error!!")
        return null;
    }

    //最底层UI用，上层UI用paramUI里的
    public ShowMsgBox(nodeBase: Node, content: string, callback: (ok) => void) {
        this.AddUI(nodeBase, 'msg_box', { label: content }, callback)
    }

    //最底层UI用，上层UI用paramUI里的
    public ShowHint(nodeBase: Node, label: string, callback: (pm) => void, pm: string = "") {
        UiManager.Instance.AddUI(nodeBase, 'hint', { label: label, param: pm }, callback)
    }


    //callbackBase关闭UI最后一层的回调，开始添加的时候，必须要传值
    public AddUI(nodeBase: Node, nameUI: string, pm: any, callbackBase: (pm) => void = null) {
        plog("add ui name:", nodeBase.name)
        // this.setParams(param);//设置UI需要的参数
        this.createUI(nameUI, (node_ui: Node) => {
            let nodeCover = this.AddCover(nodeBase, 1)//创建一层黑色遮盖背景
            nodeCover.addChild(node_ui)//黑色背景上增加UI
            node_ui.setScale(new Vec3(0, 0, 1))//UI设置最小化
            let pu = node_ui.getComponent(ParamUI)
            if (pu != null) {
                if (callbackBase !== null) {//有这个回调，说明是最底层UI打卡的
                    pu.CallFuncOpen('base', pm)
                    pu.RegisterBaseCallback(nodeBase, callbackBase)
                } else {
                    pu.CallFuncOpen(nodeBase.name, pm)//需要在onload里注册好回调
                }
            } else {
                console.error("AddUI UI:", node_ui.name, " have not paramUI component param.")
            }
            nodeCover = this.AddCover(node_ui, 0)//创建一层透明的遮盖背景
            tween(node_ui)//UI层放大
                .to(DurUiScale, { scale: new Vec3(1, 1, 1) }, {
                    easing: 'elasticOut'
                })
                .call(() => {
                    node_ui.removeChild(nodeCover)//删除透明遮盖背景
                })
                .start(); // 开始动画
        })
    }

    //移除当前UI，param：关闭的UI返回出来的参数
    public RemoveUI(curNode: Node, pm?: any) {
        let nodeCover = this.AddCover(curNode, 0)//创建一层透明的遮盖背景
        let puCur = curNode.getComponent(ParamUI)
        if (puCur === null) {
            perr("RemoveUI 1 :", curNode.name, " has not ParamUI")
            return
        }
        tween(curNode)//UI层缩小
            .to(DurUiScale, { scale: new Vec3(0, 0, 1) }, {
                easing: 'backIn'
            })
            .call(() => {
                curNode.removeChild(nodeCover)//删除透明遮盖背景                
                let nodeParent = curNode.parent//找到父节点
                nodeParent.removeChild(curNode)//父节点删子节点
                let componentCover = nodeParent.getComponent(UiCover)//父节点是遮盖层
                if (componentCover == null) {//父节点不是遮盖层。报错
                    perr("RemoveUI 2 node:", curNode.name, "up node is not cover!!")
                    return
                }
                let nodeParentUp = nodeParent.parent//找到遮盖层的父节点
                nodeParentUp.removeChild(nodeParent)//删除遮盖层
                nodeParent = nodeParentUp
                // plog("puCur...", nodeParent, puCur.NodeBase)
                if (puCur.NodeBase === nodeParent) {//最低层UI了
                    puCur.CallbackEndBase(pm)
                } else {//还有UI没关
                    let pu = nodeParent.getComponent(ParamUI)//寻找UI的参数组件//!#暂定没有参数组件为最上级的UI了
                    pu.CallFuncClose(curNode.name, pm)
                }
            })
            .start(); // 开始动画
    }

    public ChangeUI(curNode: Node, pm: any, nextUiName: string) {
        let nodeCover0 = this.AddCover(curNode, 0)//创建一层透明的遮盖背景
        let puCur = curNode.getComponent(ParamUI)
        if (puCur === null) {
            perr("RemoveUI 1 :", curNode.name, " has not ParamUI")
            return
        }
        tween(curNode)//UI层缩小
            .to(DurUiScale, { scale: new Vec3(0, 0, 1) }, {
                easing: 'backIn'
            })
            .call(() => {
                curNode.removeChild(nodeCover0)//删除透明遮盖背景                
                let nodeCoverParent1 = curNode.parent//找到父节点
                nodeCoverParent1.removeChild(curNode)//父节点删子节点
                let componentCover = nodeCoverParent1.getComponent(UiCover)//父节点是遮盖层
                if (componentCover == null) {//父节点不是遮盖层。报错
                    perr("RemoveUI 2 node:", curNode.name, "up node is not cover!!")
                    return
                }
                let nodeParentUI = nodeCoverParent1.parent//找到遮盖层的父节点
                nodeParentUI.removeChild(nodeCoverParent1)//删除遮盖层
                nodeCoverParent1 = nodeParentUI
                //////////////////////////////////////
                this.createUI(nextUiName, (newUI: Node) => {
                    let nodeCover1 = this.AddCover(nodeParentUI, 1)//创建一层黑色遮盖背景
                    nodeCover1.addChild(newUI)//黑色背景上增加UI
                    newUI.setScale(new Vec3(0, 0, 1))//UI设置最小化
                    let puNew = newUI.getComponent(ParamUI)
                    if (puNew == null) {
                        console.error("AddUI UI:", newUI.name, " have not paramUI component param.")
                        return
                    }
                    if (puCur.NodeBase === nodeParentUI) {//最低层UI了
                        puNew.TransmitCallback(puCur)
                    }
                    puNew.CallFuncOpen(curNode.name, pm)
                    nodeCover0 = this.AddCover(newUI, 0)//创建一层透明的遮盖背景
                    tween(newUI)//UI层放大
                        .to(DurUiScale, { scale: new Vec3(1, 1, 1) }, {
                            easing: 'elasticOut'
                        })
                        .call(() => {
                            newUI.removeChild(nodeCover0)//删除透明遮盖背景
                        })
                        .start(); // 开始动画
                })
            })
            .start(); // 开始动画
    }
    /**
    //callbackBase关闭UI最后一层的回调，开始添加的时候，必须要传值
    public AddUI(nodeBase: Node, nameUI: string, pm: any, callbackBase: any = null) {
        plog("add ui name:", nodeBase.name)
        // this.setParams(param);//设置UI需要的参数
        this.createUI(nameUI, (node_ui: Node) => {
            let nodeCover = this.AddCover(nodeBase, 1)//创建一层黑色遮盖背景
            nodeCover.addChild(node_ui)//黑色背景上增加UI
            node_ui.setScale(new Vec3(0, 0, 1))//UI设置最小化
            let pu = node_ui.getComponent(ParamUI)
            if (pu != null) {
                pu.CallbackRefreshUI(pm)
                if (callbackBase !== null) {
                    pu.SetBaseNode(nodeBase, callbackBase)
                }
            } else {
                console.error("AddUI UI:", node_ui.name, " have not paramUI component param.")
            }
            nodeCover = this.AddCover(node_ui, 0)//创建一层透明的遮盖背景
            tween(node_ui)//UI层放大
                .to(DurUiScale, { scale: new Vec3(1, 1, 1) }, {
                    easing: 'elasticOut'
                })
                .call(() => {
                    node_ui.removeChild(nodeCover)//删除透明遮盖背景
                })
                .start(); // 开始动画
        })
    }

    //移除当前UI，param：关闭的UI返回出来的参数
    public RemoveUI(curNode: Node, pm: any, nextUiName: string | null = null) {
        let nodeCover = this.AddCover(curNode, 0)//创建一层透明的遮盖背景
        let puCur = curNode.getComponent(ParamUI)
        if (puCur === null) {
            perr("RemoveUI 1 :", curNode.name, " has not ParamUI")
            return
        }
        tween(curNode)//UI层缩小
            .to(DurUiScale, { scale: new Vec3(0, 0, 1) }, {
                easing: 'backIn'
            })
            .call(() => {
                curNode.removeChild(nodeCover)//删除透明遮盖背景                
                let nodeParent = curNode.parent//找到父节点
                nodeParent.removeChild(curNode)//父节点删子节点
                let componentCover = nodeParent.getComponent(UiCover)//父节点是遮盖层
                if (componentCover == null) {//父节点不是遮盖层。报错
                    perr("RemoveUI 2 node:", curNode.name, "up node is not cover!!")
                    return
                }
                let nodeParentUp = nodeParent.parent//找到遮盖层的父节点
                nodeParentUp.removeChild(nodeParent)//删除遮盖层
                nodeParent = nodeParentUp
                if (nextUiName == null) {//不需要重新开启新的UI
                    if (puCur.NodeBase === nodeParent) {//最低层UI了
                        puCur.CallbackUiBase(pm)
                    } else {//还有UI没关
                        let pu = nodeParent.getComponent(ParamUI)//寻找UI的参数组件//!#暂定没有参数组件为最上级的UI了
                        if (pm != null) {
                            pu.CallbackRefreshUI(pm)//有pm的传递出去，没有PM无操作
                        }
                    }
                } else {//需要重新开启新的UI
                    this.AddUI(nodeParent, nextUiName, pm)
                }
            })
            .start(); // 开始动画
    }
    /**
    //添加一个UI，param要用到的参数
    public AddUI(nameUI: string, pm: any) {//, callback: () => void) {
        plog("-----AddUI-----", nameUI, pm)
        // this.setParams(param);//设置UI需要的参数
        this.createUI(nameUI, (node_ui: Node) => {

            let nodeCover = this.addCover(this.CurrentUiNode, 1)//创建一层黑色遮盖背景
            nodeCover.addChild(node_ui)//黑色背景上增加UI
            node_ui.setScale(new Vec3(0, 0, 1))//UI设置最小化
            if (pm != null) {
                let pu = node_ui.getComponent(ParamUI)
                if (pu != null) {
                    pu.CallbackRefreshUI(pm)
                } else {
                    console.error("AddUI UI:", node_ui.name, " have not param component param.")
                }
            }
            this.CurrentUiNode = node_ui
            nodeCover = this.addCover(node_ui, 0)//创建一层透明的遮盖背景
            tween(node_ui)//UI层放大
                .to(DurUiScale, { scale: new Vec3(1, 1, 1) }, {
                    easing: 'elasticOut'
                })
                .call(() => {
                    node_ui.removeChild(nodeCover)//删除透明遮盖背景
                })
                .start(); // 开始动画
        })
    }

    //移除当前UI，param：关闭的UI返回出来的参数
    public RemoveUI(pm: any, nextUiName: string | null = null) {
        let curNode = this.CurrentUiNode
        plog("!!! RemoveUI in:", curNode.name, pm, nextUiName)
        if (curNode == this.NodeUIBase) {
            console.error("current node is not ui")
            return
        }
        let nodeCover = this.addCover(curNode, 0)//创建一层透明的遮盖背景
        tween(curNode)//UI层缩小
            .to(DurUiScale, { scale: new Vec3(0, 0, 1) }, {
                easing: 'backIn'
            })
            .call(() => {
                if (curNode != this.CurrentUiNode) {
                    perr("is all clear ui!!!!!!!")
                    return
                }
                curNode.removeChild(nodeCover)//删除透明遮盖背景
                let nodeParent = curNode.parent
                nodeParent.removeChild(curNode)
                let componentCover = nodeParent.getComponent(UiCover)
                while (componentCover != null) {
                    if (nodeParent == this.NodeUIBase) {
                        break;
                    }
                    let nodeParentUp = nodeParent.parent
                    nodeParentUp.removeChild(nodeParent)
                    nodeParent = nodeParentUp
                    componentCover = nodeParent.getComponent(UiCover)
                }
                this.CurrentUiNode = nodeParent
                if (nextUiName == null) {//不需要重新开启新的UI
                    plog("RemoveUI:", pm, nodeParent.name)
                    if (nodeParent == this.NodeUIBase) {//ui全关了
                        this.EndUI(pm)
                    } else {//还有UI没关
                        if (pm != null) {
                            let pu = nodeParent.getComponent(ParamUI)
                            if (pu != null) {
                                pu.CallbackRefreshUI(pm)
                            } else {
                                console.error("RemoveUI UI:", nodeParent.name, " have not param component param.")
                            }
                        }
                    }
                } else {//需要重新开启新的UI
                    this.AddUI(nextUiName, pm)
                }
            })
            .start(); // 开始动画
    }
    /**/

    private EndUI(pm: any) {
        plog("EndUI:", this.node.name)
        if (this.EndUiCallback != null) {
            this.EndUiCallback(pm)
            this.EndUiCallback = null
        }
    }

    public SetEndUiCallback(func: (pm: any) => void) {
        this.EndUiCallback = func
    }

    // public ClearAllUI() {
    //     plog("ClearAllUI in.....")
    //     this.NodeUIBase.removeAllChildren()
    //     this.CurrentUiNode = this.NodeUIBase
    //     plog("ClearAllUI out.....")
    // }
    // public GetParams(): any {
    //     return this.Params
    // }

    // setParams(pm: any): void {
    //     this.Params = pm
    // }

    // public OpenUI(nameUI: string, callback) {
    //     plog("OpenUI", nameUI, callback)
    //     let callbackOpenUI = () => {
    //         this.BundleGUI.load(nameUI, Prefab, (err, data: Prefab) => {
    //             if (err) {
    //                 plog(err)
    //                 return
    //             }
    //             this.CurrentUiNode = instantiate(data);
    //             this.CurrentUiNode.setScale(new Vec3(0, 0, 1))
    //             this.NodeUI.addChild(this.CurrentUiNode);
    //             tween(this.CurrentUiNode)
    //                 .to(0.5, { scale: new Vec3(1, 1, 1) })
    //                 .call(() => {
    //                     callback()
    //                 })
    //                 .start(); // 开始动画
    //         })
    //     }
    //     if (this.CurrentUiNode) {
    //         tween(this.CurrentUiNode)
    //             .to(0.5, { scale: new Vec3(0, 0, 1) })
    //             .call(() => {
    //                 this.NodeUI.removeChild(this.CurrentUiNode)
    //                 callbackOpenUI()
    //             })
    //             .start(); // 开始动画
    //     } else {
    //         callbackOpenUI()
    //     }
    // }

    start() {

    }

    update(deltaTime: number) {

    }

    onDestroy() {

    }

}


